package com.template.websocket;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.template.bigModel.BigModelUtil;
import com.template.dto.GroupMessage;
import com.template.dto.User;
import com.template.service.MessageService;
import com.template.utils.SpringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * WebSocket 连接测试tomcat
 */
@Component
@ServerEndpoint("/web-socket/{userId}")
public class WebSocketUtil {

//    private BigModelUtil bigModelUtil;

    private User user;
    private Session session;

    /** 固定前缀  */
    private static final String USER_ID_PREFIX = "user_name_";

    /**
     * 用来存放每个客户端对应的WebSocketUtil对象。
     */
    private static CopyOnWriteArraySet<WebSocketUtil> webSocketSet = new CopyOnWriteArraySet<>();

    /**
     * 存放Session集合，方便推送消息 （javax.websocket.Session）
     */
    private static ConcurrentHashMap<String, Session> sessionMap = new ConcurrentHashMap<>();

//    public WebSocketUtil(BigModelUtil bigModelUtil) {
//        this.bigModelUtil = bigModelUtil;
//    }

    /**
     * 私聊：向指定客户端推送消息
     * @param socketMsg 消息对象
     */
    public synchronized static void privateMessage(GroupMessage groupMessage) {
//        // 获取接收消息的用户
//        Session receiveUser = sessionMap.get(USER_ID_PREFIX + groupMessage.getReceiveUser());
//        if (receiveUser != null) {
//            // 发送给接收者
//            System.out.println(socketMsg.getSendOutUser() + " 向 " + socketMsg.getReceiveUser() + " 发送了一条消息：" + socketMsg.getMsg());
//            receiveUser.getAsyncRemote().sendText(socketMsg.getSendOutUser() + "：" + socketMsg.getMsg());
//        } else {
//            // 发送消息的用户
//            System.out.println(socketMsg.getSendOutUser() + " 私聊的用户 " + socketMsg.getReceiveUser() + " 不在线或者输入的用户名不对");
//            Session sendOutUser = sessionMap.get(USER_ID_PREFIX + socketMsg.getSendOutUser());
//            // 将系统提示推送给发送者
//            sendOutUser.getAsyncRemote().sendText("系统消息：对方不在线或者您输入的用户名不对");
//        }
    }


    public synchronized static void AIMessage(GroupMessage groupMessage) throws Exception {
        // 获取接收消息的用户
        Session receiveUser = sessionMap.get(USER_ID_PREFIX + groupMessage.getId());
//        if (receiveUser != null) {
            // 发送给接收者
        BigModelUtil bigModelUtil=new BigModelUtil();
        new Thread(()->{
            try{

                bigModelUtil.start(groupMessage.getMessage(),receiveUser, String.valueOf(groupMessage.getId()));
            }catch (Exception e){
                e.printStackTrace();
            }
        }).start();
//            System.out.println(socketMsg.getSendOutUser() + " 向 " + socketMsg.getReceiveUser() + " 发送了一条消息：" + socketMsg.getMsg());
//            receiveUser.getAsyncRemote().sendText(groupMessage.getSendOutUser() + "：" + socketMsg.getMsg());
//        } else {
//            // 发送消息的用户
//            System.out.println(socketMsg.getSendOutUser() + " 私聊的用户 " + socketMsg.getReceiveUser() + " 不在线或者输入的用户名不对");
//            Session sendOutUser = sessionMap.get(USER_ID_PREFIX + socketMsg.getSendOutUser());
//            // 将系统提示推送给发送者
//            sendOutUser.getAsyncRemote().sendText("系统消息：对方不在线或者您输入的用户名不对");
//        }
    }

    /**
     * 群聊：公开聊天记录
     * @param userId 发送者的用户名称（当前用户）
     * @param message 发送的消息
     * @param flag 用来标识是否要将消息推送给当前用户
     */
//    synchronized：方法是同步的，确保在同一时间只有一个线程可以执行该方法，避免多线程并发问题。
    public synchronized static void publicMessage(GroupMessage groupMessage) {
        JSONObject message = JSONUtil.parseObj(groupMessage);
        try {
            LocalDateTime currentDateTime=LocalDateTime.now();
//            GroupMessage domain = JSONUtil.toBean(message,GroupMessage.class);
            groupMessage.setCreateTime(currentDateTime);
//            筛选掉用来通知的数据
            if(groupMessage.getId()!=0){
                MessageService messageService= SpringUtils.getBean(MessageService.class);
                messageService.insertMessage(groupMessage);
            }
//            System.out.println("客户端发送的信息"+domain);
            for (WebSocketUtil item : webSocketSet) {
                Session session = item.session;
//            if (flag) {
                session.getAsyncRemote().sendText(String.valueOf(message));
//            } else {
//                // 获取发送这条消息的用户
//                Session currentUser = sessionMap.get(USER_ID_PREFIX + userId);
//                // 消息不用推送到发送者的客户端
//                if (!session.getId().equals(currentUser.getId())) {
//                    session.getAsyncRemote().sendText(message);
//                }
//            }
            }
//            System.out.println("公共频道接收了一条消息：" + message);
        }catch (Exception e){
            // 打印异常信息
            e.printStackTrace();
            // 打印引起异常的 JSON 字符串
            System.out.println("引起异常的 JSON 字符串: " + message);
            // 打印异常的具体信息
            System.out.println("异常信息: " + e.getMessage());
        }
    }

    /**
     * 监听：连接成功
     * @param session WebSocket会话
     * @param userId 连接的用户名
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") Integer userId) throws IOException {
        MessageService messageService = SpringUtils.getBean(MessageService.class);
        this.user = messageService.selectById(userId);
//        System.out.println(user);

//        System.out.println("前端传来的用户id" + userId);
        this.session = session;

        // 检查是否已有相同ID的连接
        if (sessionMap.containsKey(USER_ID_PREFIX + userId)) {
            // 如果存在旧会话，先关闭旧会话
            Session oldSession = sessionMap.get(USER_ID_PREFIX + userId);
            oldSession.close();
            // 移除旧会话的相关记录
            webSocketSet.remove(this);
            sessionMap.remove(USER_ID_PREFIX + userId);
        }

        // 添加新的会话到集合中
        sessionMap.put(USER_ID_PREFIX + userId, session);
        webSocketSet.add(this);

        // 在线数加1
        String online = user.getName() + " 加入聊天室";
        System.out.println(online + webSocketSet.size());
        GroupMessage onMessage = new GroupMessage();
        onMessage.setId(0L);
        onMessage.setName(String.valueOf(webSocketSet.size()));
        onMessage.setMessage(online);
        onMessage.setType(1);
//        String message1 = String.valueOf(JSONUtil.parse(onMessage));
        publicMessage(onMessage);
    }

    /**
     * 监听：收到客户端发送的消息
     * @param message 发送的信息（json格式，里面是 SocketMsg 的信息）
     */
    @OnMessage
    public void onMessage(String message) throws Exception {
        System.out.println("客户端发过来的信息"+message);
        if (JSONUtil.isTypeJSONObject(message)) {
            GroupMessage domain = JSONUtil.toBean(message, GroupMessage.class);
            if (domain.getType() == 1) {
                // 群发消息
                publicMessage(domain);
            } else if(domain.getType()==3) {
                // AI
                AIMessage(domain);
            }
        }
    }

    /**
     * 监听: 连接关闭
     */
    @OnClose
    public void onClose(Session session, @PathParam("userId") Integer userId) {
        if (sessionMap.containsKey(USER_ID_PREFIX + userId)) {
            // 连接关闭后，将此WebSocket从set中删除
            sessionMap.remove(USER_ID_PREFIX + userId);
            webSocketSet.remove(this);
        }
        String offline = user.getName() + " 退出聊天室";
        System.out.println(offline);
        GroupMessage offMessage=new GroupMessage();
        offMessage.setId(0L);
        offMessage.setName(String.valueOf(webSocketSet.size()));
        offMessage.setMessage(offline);
        offMessage.setType(1);
//        String message1= String.valueOf(JSONUtil.parse(offMessage));
        publicMessage(offMessage);
    }

    /**
     * 监听：发生异常
     * @param error 异常信息
     */
    @OnError
    public void onError(Throwable error) {
//        System.out.println("userName为：" + userId + "，发生错误：" + error.getMessage());
        error.printStackTrace();
    }
}